package cn.modoumama;

import cn.modoumama.dto.GDAODetailInfoDto;
import cn.modoumama.utils.GDAOToolsConst.CUSTOM_SOURCE;
import cn.modoumama.utils.GDAOToolsUtil;
import cn.modoumama.utils.VelocityUtil;
import org.apache.commons.lang.StringUtils;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.*;


public class GDAOToolsMain {

    /**
     * SQL 类型配置信息
     */
    public static Properties sqlTypeProperties;
    /**
     * DB数据库连接
     */
    private static Connection conn;
    /**
     * 配置信息
     */
    private static Properties configProperties;
    /**
     * 操作人
     */
    private static final String AUTHOR = configProperties.getProperty("AUTHOR");
    /**
     * 包名
     */
    private static final String PACKAGE = configProperties.getProperty("PACKAGE");
    /**
     * 实体类包
     */
    private static final String MODEL_PACKAGE = configProperties.getProperty("MODEL_PACKAGE");
    /**
     * 业务类接口包
     */
    private static final String SERVICE_INTERFACE_PACKAGE = configProperties.getProperty("SERVICE_INTERFACE_PACKAGE");
    /**
     * DAO包
     */
    private static final String DAO_PACKAGE = configProperties.getProperty("DAO_PACKAGE");
    /**
     * 业务类实现包
     */
    private static final String SERVICE_IMPLEMENTS_PACKAGE = configProperties.getProperty("SERVICE_IMPLEMENTS_PACKAGE");
    /**
     * Model类 后缀
     */
    private static final String MODEL_CLASS = configProperties.getProperty("MODEL_CLASS");
    /**
     * DAO类 后缀
     */
    private static final String DAO_CLASS = configProperties.getProperty("DAO_CLASS");
    /**
     * Model类 后缀
     */
    private static final String SERVICE_INTERFACE_CLASS = configProperties.getProperty("SERVICE_INTERFACE_CLASS");
    /**
     * Model类 后缀
     */
    private static final String SERVICE_IMPLEMENTS_CLASS = configProperties.getProperty("SERVICE_IMPLEMENTS_CLASS");
    /**
     * 分库前缀信息配列
     */
    private static final String[] SUB_LIBRARY_PREX = configProperties.getProperty("SUB_LIBRARY_PREX").split(",");
    //读取模板配置信息
    private static final String MODEL_TEMPLATE_FILE = configProperties.getProperty("MODEL_TEMPLATE_FILE");
    //dao接口定义模板
    private static final String DAO_INTERFACE_TEMPLATE_FILE = configProperties.getProperty("DAO_INTERFACE_TEMPLATE_FILE");
    //mapper定义模板
    private static final String DAO_SQL_MAP_TEMPLATE_FILE = configProperties.getProperty("DAO_SQL_MAP_TEMPLATE_FILE");
    //业务类接口定义模板
    private static final String SERVICE_INTERFACE_TEMPLATE_FILE = configProperties.getProperty("SERVICE_INTERFACE_TEMPLATE_FILE");
    //业务类实现定义模板
    private static final String SERVICE_IMPLEMENTS_TEMPLATE_FILE = configProperties.getProperty("SERVICE_IMPLEMENTS_TEMPLATE_FILE");
    //分库文件输出路径
    private static final String OUTPUT_PATH = configProperties.getProperty("OUTPUT_PATH");
    private static final String MODEL_OUTPUT_PATH = configProperties.getProperty("MODEL_OUTPUT_PATH");
    private static final String DAO_OUTPUT_PATH = configProperties.getProperty("DAO_OUTPUT_PATH");
    private static final String SERVICE_INTERFACE_OUTPUT_PATH = configProperties.getProperty("SERVICE_INTERFACE_OUTPUT_PATH");
    private static final String SERVICE_IMPLEMENTS_OUTPUT_PATH = configProperties.getProperty("SERVICE_IMPLEMENTS_OUTPUT_PATH");

    static {
        //初始化数据
        try {
            initData();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * dao信息list
     */
    private List<GDAODetailInfoDto> gdaoDetailInfoDtoList = new ArrayList<GDAODetailInfoDto>();

    /**
     * 初始化数据
     *
     * @throws Exception
     */
    private static void initData() throws Exception {
        /**
         * classes目录下使用
         */
//		InputStream config = getClass().getClassLoader().getResourceAsStream("con/ToolsConfig.properties");
//		InputStream sqlType = getClass().getClassLoader().getResourceAsStream("types.properties");

        InputStream config = new FileInputStream("conf/ToolsConfig.properties");
        InputStream sqlType = new FileInputStream("conf/types.properties");


        //ToolsConfig配置文件读取
        configProperties = GDAOToolsUtil.readPropertiesByInputStream(config);

        //types配置文件读取
        sqlTypeProperties = GDAOToolsUtil.readPropertiesByInputStream(sqlType);

    }

    public static void main(String[] args) throws Exception {

        GDAOToolsMain toolsMain = new GDAOToolsMain();

        toolsMain.execute();

    }

    /**
     * 生成dao代码
     *
     * @throws Exception
     */
    private void execute() throws Exception {
        Map<String, Object> paramMap = new HashMap<String, Object>();

        //设置sql map的模板名称
        paramMap.put("sqlMapClientTemplate", configProperties.getProperty("SQL_MAP_CLIENT_TEMPLATE"));

        for (int i = 0; i < SUB_LIBRARY_PREX.length; i++) {
            //获取需要生成的表
            String db_table_name_list = configProperties.getProperty(SUB_LIBRARY_PREX[i] + "DB_TABLE_NAME_LIST");
            //表对应的seq
            String db_table_seq_name_list = configProperties.getProperty(SUB_LIBRARY_PREX[i] + "DB_TABLE_SEQ_NAME_LIST");

            String[] tableArray = db_table_name_list.split(",");
            String[] tableSeqArray = null;

            if (!GDAOToolsUtil.isEmpty(db_table_seq_name_list)) {
                tableSeqArray = db_table_seq_name_list.split(",");
            }

            if (tableSeqArray != null && tableSeqArray.length > 0 && tableArray.length != tableSeqArray.length) {
                System.out.println("您设置的表名和表对应的seq名数量有误，请确认分库" + SUB_LIBRARY_PREX[i]);
                System.out.println("表数量：" + tableArray.length + "  表对应seq数量：" + tableSeqArray.length);
                return;
            }

            if (tableArray.length == 1 && StringUtils.isEmpty(tableArray[0])) {
                continue;
            } else {
                //数据库连接获取
                conn = GDAOToolsUtil.getConnection(SUB_LIBRARY_PREX[i], configProperties);
            }

            for (int j = 0; tableArray != null && j < tableArray.length; j++) {
                if (!GDAOToolsUtil.isEmpty(tableArray[j])) {

                    try {
                        //单表生成源码
                        generateSourceWithCustomSource(tableArray[j]);
                        System.out.println(tableArray[j] + " : OK");
                    } catch (Exception e) {
                        System.out.println("---------------" + tableArray[j] + "-----------------");
                        e.printStackTrace();
                        System.out.println("表" + tableArray[j] + "的代码无法生成  " + e.getMessage() + " 分库： " + SUB_LIBRARY_PREX[i]);
                    }
                }
            }
        }
    }

    /**
     * @param table 表名
     * @throws Exception
     * @Description:根据单表自动生成源码 <br/>
     * @author 邓强
     * @date 2017年2月10日 下午1:52:46
     */
    public void generateSourceWithCustomSource(String table) throws Exception {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        GDAODetailInfoDto detailInfoDto = GDAOToolsUtil.getGDAODetailInfo(conn, table, sqlTypeProperties, configProperties.getProperty("MYSQL_DB_SCHEMA"));
        detailInfoDto.setTableName(table.toUpperCase());

        paramMap.put("detailInfoDto", detailInfoDto);
        paramMap.put("author", AUTHOR);
        Long currentTimeMillis = System.currentTimeMillis();
        paramMap.put("date", new java.sql.Date(currentTimeMillis));
        paramMap.put("time", new java.sql.Time(currentTimeMillis));
        String modelPackage = generateModelSource(paramMap, detailInfoDto);
        String daoPackage = generateDaoSource(paramMap, detailInfoDto, modelPackage);
        generateServiceSource(paramMap, detailInfoDto, modelPackage, daoPackage);
        gdaoDetailInfoDtoList.add(detailInfoDto);
    }

    private String generateModelSource(Map<String, Object> paramMap, GDAODetailInfoDto detailInfoDto) {
        String className = detailInfoDto.getClassName() + MODEL_CLASS;
        String packageName = PACKAGE + MODEL_PACKAGE;
        String outputPath = OUTPUT_PATH + "/" + MODEL_OUTPUT_PATH;
        paramMap.put("packageName", packageName);

        String dao_model_source = VelocityUtil.generateSourceWithCustomSource(MODEL_TEMPLATE_FILE, paramMap,
                CUSTOM_SOURCE.MODEL, packageName, className, outputPath);
        //代码文件输出
        VelocityUtil.printToFile(packageName, className, dao_model_source, outputPath, "java");
        return packageName + "." + className;

    }

    private String generateDaoSource(Map<String, Object> paramMap, GDAODetailInfoDto detailInfoDto, String modelPackage) {
        List<String> packageNameList = new ArrayList<>();
        packageNameList.add(modelPackage);

        detailInfoDto.setPackageNameList(packageNameList);


        String className = detailInfoDto.getClassName() + DAO_CLASS;
        String packageName = PACKAGE + DAO_PACKAGE;
        String outputPath = OUTPUT_PATH + "/" + DAO_OUTPUT_PATH;
        paramMap.put("packageName", packageName);
        //生成dao代码(mapper)
        String dao_source = VelocityUtil.generateSourceWithCustomSource(DAO_INTERFACE_TEMPLATE_FILE, paramMap,
                CUSTOM_SOURCE.DAO, packageName, className, outputPath);
        //生成xml(mapper)
        String dao_sql_map_source = VelocityUtil.generateSourceWithCustomSource(DAO_SQL_MAP_TEMPLATE_FILE, paramMap,
                CUSTOM_SOURCE.SQL_MAP, packageName, className, outputPath);

        VelocityUtil.printToFile(packageName, className, dao_source, outputPath, "java");
        VelocityUtil.printToFile(packageName, className, dao_sql_map_source, outputPath, "xml");
        return packageName + "." + className;

    }

    private String generateServiceSource(Map<String, Object> paramMap, GDAODetailInfoDto detailInfoDto, String modelPackage, String daoPackage) {
        List<String> packageNameList = new ArrayList<>();
        packageNameList.add(modelPackage);
        detailInfoDto.setPackageNameList(packageNameList);


        String interfaClassName = detailInfoDto.getClassName() + SERVICE_INTERFACE_CLASS;
        String interfacPackageName = PACKAGE + SERVICE_INTERFACE_PACKAGE;
        String interfacOoutputPath = OUTPUT_PATH + "/" + SERVICE_INTERFACE_OUTPUT_PATH;
        paramMap.put("packageName", interfacPackageName);
        //生成业务接口代码
        String dao_source = VelocityUtil.generateSourceWithCustomSource(SERVICE_INTERFACE_TEMPLATE_FILE, paramMap,
                CUSTOM_SOURCE.SERVICE, interfacPackageName, interfaClassName, interfacOoutputPath);
        VelocityUtil.printToFile(interfacPackageName, interfaClassName, dao_source, interfacOoutputPath, "java");

        String implementsClassName = detailInfoDto.getClassName() + SERVICE_IMPLEMENTS_CLASS;
        String implementsPackageName = PACKAGE + SERVICE_IMPLEMENTS_PACKAGE;
        String implementsOutputPath = OUTPUT_PATH + "/" + SERVICE_IMPLEMENTS_OUTPUT_PATH;
        paramMap.put("packageName", implementsPackageName);
        packageNameList.add(daoPackage);
        packageNameList.add(interfacPackageName + "." + interfaClassName);
        //生成业务实现类代码
        String dao_sql_map_source = VelocityUtil.generateSourceWithCustomSource(SERVICE_IMPLEMENTS_TEMPLATE_FILE, paramMap,
                CUSTOM_SOURCE.SERVICE_IMPL, implementsPackageName, implementsClassName, implementsOutputPath);


        VelocityUtil.printToFile(implementsPackageName, implementsClassName, dao_sql_map_source, implementsOutputPath, "java");
        return null;
    }
}
